<template>
  <!-- 模型展示弹框，在这里主要展示上传后的模型 -->
  <div v-if="dialogVisible" class="model-show-dialog">
    <el-dialog :title="$t('tool.modelManage.modelDisplay')" :visible.sync="dialogVisible" :close-on-click-modal="false"
      width="800px" @close="handleClose">
      <p v-if="!isShowOnly" style="text-align: center; color: var(--app-primary-base);">
        {{ $t('tool.modelManage.modelTips') }}
      </p>
      <div class="three-model-container" id="model-display"></div>
      <div v-if="!isShowOnly && loadingCompleted" slot="footer" class="dialog-footer">
        <el-button :loading="isUploadImg" class="jtyj-btn-primary" @click="submitForm">{{
          $t("setup.buttonText.confirm")
        }}</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from "@/utils/auth";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment";
import { MeshoptDecoder } from "three/examples/jsm/libs/meshopt_decoder.module";
import { uploadThreeDimensionFile } from "@/api/myspace/model-manage-tool/model-manage";
import { mapState } from "vuex";
var scene;
var camera;
var renderer;
var control;
export default {
  data() {
    return {
      loadingCompleted: false,
      dialogVisible: false,
      isUploadImg: false, // 判断是否上传了图片
      isShowOnly: false, // 是否是只展示
      modelFileInfo: null,
      folderInfo: {},
      form: {},
    };
  },
  computed: {
    ...mapState({
      userId: (state) => state.user.id,
    }),
  },
  mounted() {
    this.$EventBus.$on("fileSuccess", (response) => {
      if (response.data.fileType != "png") return;
      if (response.code != 200) {
        this.$message.error(
          this.$toolHandle.getI18nName(
            this.$zh.setup.responseText,
            this.$en.setup.responseText,
            this.$i18n.locale,
            "error"
          )
        );
        return;
      } else {
        this.form.fileImageUrl = response.data.filePath;
        this.form.fileName = response.data.fileName;
        if (this.isUploadImg) {
          this.commitData();
        }
      }
    });
  },
  methods: {
    init(modelFileInfo, folderInfo, isShowOnly) {
      this.dialogVisible = true;
      this.isUploadImg = false;
      this.isShowOnly = isShowOnly;
      this.modelFileInfo = JSON.parse(JSON.stringify(modelFileInfo));
      this.folderInfo = folderInfo;
      this.reset(folderInfo);
      this.$nextTick(() => {
        this.initCanvas();
      });
    },
    initCamera(domDiv) {
      camera = new THREE.PerspectiveCamera(
        45,
        domDiv.offsetWidth / domDiv.offsetHeight,
        1,
        2200
      );
      camera.position.set(-70, 50, 50);
      //设置相机默认看向哪里   三个 0  代表 默认看向原点
      camera.lookAt(0, 0, 0);
    },
    initControl() {
      // 控制器
      control = new OrbitControls(camera, renderer.domElement);
      setTimeout(() => {
        this.loader();
      }, 1000);
    },
    //初始化
    initCanvas() {
      const domDiv = document.getElementById("model-display");
      // 场景，相机
      scene = new THREE.Scene();
      this.initCamera(domDiv);

      // 渲染器
      // 参数 antialias: true 为开启抗锯齿
      renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setSize(domDiv.offsetWidth, domDiv.offsetHeight);
      renderer.setClearColor(0x000000, 0);
      domDiv.appendChild(renderer.domElement);
      // 材质
      const environment = new RoomEnvironment();
      const pmremGenerator = new THREE.PMREMGenerator(renderer);
      scene.environment = pmremGenerator.fromScene(environment).texture;
      this.initControl();
      // 坐标系
      //   const axesHelper = new THREE.AxesHelper(14);
      //   scene.add(axesHelper);
      function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
      }
      animate();
    },
    loader() {
      const _this = this;
      const loader = new GLTFLoader();
      loader.load(
        process.env.VUE_APP_BASE_API + this.modelFileInfo.path,
        (gltf) => {
          scene.add(_this.editModel(gltf.scene));
          renderer.render(scene, camera);
          this.loadingCompleted = true;
        }
      );
    },
    // 调整模型缩放
    editModel(_scene) {
      const boxHelper = new THREE.BoxHelper(_scene);
      boxHelper.geometry.computeBoundingBox();
      const box = boxHelper.geometry.boundingBox;
      const maxDiameter = Math.max(
        box.max.x - box.min.x,
        box.max.y - box.min.y,
        box.max.z - box.min.z
      );
      const scale = camera.position.z / maxDiameter;
      _scene.scale.set(scale, scale, scale); // 调整模型缩放
      _scene.position.set(0, 0, 0);
      return _scene;
    },
    // 截屏方法
    screenPic() {
      return new Promise((resolve, reject) => {
        let canvas = renderer.domElement;
        renderer.render(scene, camera);
        const imgUrl = canvas.toDataURL("image/png", 1.0);
        resolve(this.base64ToFile(imgUrl, this.folderInfo.fileName));
      });
    },
    // base64编码图片转file格式
    base64ToFile(base64, fileName) {
      if (typeof base64 != "string") {
        return;
      }
      var arr = base64.split(",");
      var type = arr[0].match(/:(.*?);/)[1];
      var fileExt = type.split("/")[1];
      var bstr = atob(arr[1]);
      var n = bstr.length;
      var u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], `${fileName}.` + fileExt, {
        type: type,
      });
    },
    reset(folderInfo) {
      this.form = {
        fileId: null, //模型文件ID
        fileName: null, //模型文件名称
        fileUrl: this.modelFileInfo.path, //模型文件 URL 地址
        fileImageUrl: null, //模型文件图片 URL 地址
        parentId: folderInfo.fileId, //父级ID
        ancestors: folderInfo.ancestors, //祖级列表
        orderNum: folderInfo.orderNum, //显示顺序
        nodeType: 1, //节点类型：0 文件夹，1 文件
        userId: this.userId, //创建人ID
        delFlag: folderInfo.delFlag, //删除标志（0代表存在 2代表删除）
      };
    },
    // 点击提交按钮
    submitForm() {
      this.screenPic().then((res) => {
        this.isUploadImg = true;
        this.$EventBus.$emit("openUploader", {
          token: getToken(),
          prefixFlag: 1,
          userId: this.userId,
          fileObject: res,
        });
      });
    },
    // 提交上传的模型以及模型图片
    commitData() {
      let formData = {
        fileName: this.form.fileName,
        fileUrl: this.form.fileUrl,
        fileImageUrl: this.form.fileImageUrl,
        parentId: this.form.parentId,
        // ancestors: this.form.ancestors,
        // orderNum: this.form.orderNum,
        nodeType: 1,
        userId: this.userId,
        // delFlag: this.form.delFlag,
      };
      uploadThreeDimensionFile(formData)
        .then((response) => {
          if (response.code == 200) {
            this.$message.success(
              this.$toolHandle.getI18nName(
                this.$zh.setup.responseText,
                this.$en.setup.responseText,
                this.$i18n.locale,
                "success"
              )
            );
            this.$emit("refreshList");
            this.handleClose();
          } else {
            this.$message.error(
              this.$toolHandle.getI18nName(
                this.$zh.setup.responseText,
                this.$en.setup.responseText,
                this.$i18n.locale,
                "error"
              )
            );
          }
        })
        .catch(() => { });
    },
    // 切换路由时清除场景
    disposeScene(scene) {
      while (scene.children.length > 0) {
        let obj = scene.children[0];
        scene.remove(obj);
        if (obj.geometry) {
          obj.geometry.dispose();
        }
        if (obj.material) {
          if (Array.isArray(obj.material)) {
            obj.material.forEach((material) => {
              material.dispose();
            });
          } else {
            obj.material.dispose();
          }
        }
      }
      renderer.clear();
    },
    handleClose() {
      this.disposeScene(scene);
      this.dialogVisible = false;
      this.loadingCompleted = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.three-model-container {
  width: 700px;
  height: 500px;
  border: 2px dotted var(--ui-border-color-base);
  margin: 0 auto;
}
</style>